# pragma once 

# include <vector>

# include <iostream>

namespace memtool {

    template <size_t ChunkSize>
    class SequentalMemoryAllocator {
        typedef std::vector<char*> chunk_storage_type;
    public:

        SequentalMemoryAllocator(size_t bs)
            : chunks_(), blockSize_(bs), next_(new char[bs*ChunkSize]), blockNumber_(0), blockPosition_(0) 
        {
            chunks_.push_back(next_);
        }

        ~SequentalMemoryAllocator() {
            releaseAll();
        }

        void* alloc() {
            if (blockPosition_ == blockSize_) {
                if (blockNumber_ == chunks_.size()-1) {
                    char* ptr = new char[ChunkSize*blockSize_];
                    chunks_.push_back(ptr);
                }
                next_ = chunks_[++blockNumber_];
                blockPosition_ = 0;
            }

            blockPosition_ += 1;
            void* rv = static_cast<void*>(next_);
            next_ += ChunkSize;
            return rv;
        }

      
        void release() {
            blockNumber_ = 0;
            blockPosition_ = 0;
            next_ = chunks_[0];
        }

        void releaseAll() {
            for (chunk_storage_type::iterator iter = chunks_.begin(); iter != chunks_.end(); ++iter) 
                delete *iter;
            chunks_.clear();
        }

    private:
        SequentalMemoryAllocator(SequentalMemoryAllocator&);
        SequentalMemoryAllocator& operator=(SequentalMemoryAllocator&);

    private:
        chunk_storage_type chunks_;
        size_t const blockSize_;
        char* next_;

        size_t blockPosition_;
        size_t blockNumber_;
    };

}
